package com.gitee.wsl.coroutines.executor.sample

import com.gitee.wsl.concurrent.api.RunnableWithResult
import com.gitee.wsl.coroutines.executor.KExecutor
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update

/**
 * Executor which executes operation atomically.
 */
class AtomicExecutor: KExecutor {
    private val _executing = MutableStateFlow(false)
    val executing = _executing.asStateFlow()

    /**
     * Executes the [block] atomically.
     * If already any operation is executing, it'll wait till its completion.
     */
    override fun <T> execute(block: RunnableWithResult<T>):T {
        while (true) {
            if (_executing.compareAndSet(expect = false, update = true)) {
                try {
                    return block.run()
                } finally {
                    _executing.update { false }
                }
            }
        }
    }

    companion object{
        val INSTANCE = AtomicExecutor()
    }
}

fun KExecutor.Companion.atomicExecutor() = AtomicExecutor.INSTANCE